<?php

/**
 * @see Zend_Filter_Interface
 */
require_once 'Zend/Filter/Interface.php';


/**
 * Polyline GMap
 *
 * @category   Core
 * @package    Core_Filter_Google_Maps
 * @link       http://andreaskalsch.de/blog/2008/03/16/Adapting%20a%20Polyline%20Encoder%20to%20PHP
 * @license    GPL
 * @copyright  Copyright (c) 2008 Kuśmierz Adam
 * @author     Andreas Kalsch
 */
class Core_Filter_Google_Maps_EncodePolyline implements Zend_Filter_Interface
{
	/**
	 * Encode a signed number in the encode format
	 *
	 * @param int $number
	 * @return string
	 */
	protected function encodeSignedNumber($number)
	{
		$signedNumber = $number << 1;
		
		if ($number < 0)
			$signedNumber = ~($signedNumber);
	
		return $this->encodeNumber($signedNumber);
	}
	
	/**
	 * Encode an unsigned number in the encode format
	 *
	 * @param int $number
	 * @return string
	 */
	protected function encodeNumber($number)
	{
		$encodeString = '';
		
		while ($number >= 0x20) {
			$encodeString .= (chr((0x20 | ($number & 0x1f)) + 63));
			$number >>= 5;
		}
		
		$encodeString .= (chr($number + 63));
		
		return $encodeString;
	}
	
	/**
	 * Defined by Zend_Filter_Interface
	 *
	 * Returns (string) $value
	 *
	 * @param  array $value
	 * @return string
	 */
	public function filter($value)
	{
		if (!is_array($value))
			return false;
		
		$plat = 0;
		$plng = 0;
		
		$encoded_points = '';
		$encoded_levels = '';
		
		foreach ($value as $point) {
			if (!isset($point['x']) || !isset($point['y']))
				return false;
			$level = 3;
			
			$late5 = floor($point['x'] * 1e5);
			$lnge5 = floor($point['y'] * 1e5);
			
			$dlat = $late5 - $plat;
			$dlng = $lnge5 - $plng;
			
			$plat = $late5;
			$plng = $lnge5;
			
			$encoded_points .= $this->encodeSignedNumber($dlat) . $this->encodeSignedNumber($dlng);
			$encoded_levels .= $this->encodeNumber($level);
		}
		
		return array('polyline' => $encoded_points, 'levels' => $encoded_levels);
	}
}
